/*->c.ascii */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <string.h>


#include "h.os"
#include "h.wimp"
#include "h.sprite"
#include "h.werr"
#include "h.wimpt"
#include "h.bbc"
#include "h.akbd"


#include "h.def"
#include "h.swis"

#include "h.wos"
#include "h.timex"
#include "h.trans"

#include "h.serial"
#include "h.key"

#include "h.view"
#include "h.mym"
#include "h.batch"
#include "h.ftp"
#include "h.term"
#include "h.main"

#include "h.xmodem"



/*****************************************************************************/
                     /********** ASCII FTP ************/



 int asctxe=0;            /* send echo on */
 int ascrxe=0;            /* receive echo on */

 int txprompt=-1;
 int txeol=ASCIICRLF;
 int txstart=-1;
 int txstop=-1;
 int txbegin=-1;
 int txend=SUB;
 int txcharpace=0;
 int txlinepace=0;
 int txexpand;

 int rxbegin=-1;
 int rxend=SUB;
 int rxprompt=-1;
 int rxeol=ASCIICR;
 int rxtprompt=-1;        /* continue */
 int rxpace=0;            /* not a pace, a timeout */


/*****************************************************************************/



int xasciichar(int handle,int icon)    /* return either code or -1 */
{
 return(codechar(iconaddr(handle,icon)));
}


static void xasciigetchar(int * val,int handle,int icon)
{
 int c;
 c=xasciichar(handle,icon);
 *val=c;
}



void xasciiwrchar(int handle,int icon,int byte)
{
 char * string;

 string=iconaddr(handle,icon);

 if(byte==-1) *string=0;
 else         uncode(string,byte);
}


static int xasciipace(int handle,int icon)  /* return either pace or -1 */
{
 int    i;
 char * string;

 string=iconaddr(handle,icon);

 sscanf(string,"%d",&i);
 return(i>=0?i:-1);
}


void xasciigetpace(int handle,int icon,int * val)
{
 int c;
 c=xasciipace(handle,icon);
 if(c!=-1) *val=c;
}


void xasciigetpace10(int handle,int icon,int * val)
{
 int c;
 c=xasciipace(handle,icon);
 if(c!=-1) *val=c*10;
}



void xasciiwrpace(int handle,int icon,int pace)
{
 char * string;
 string=iconaddr(handle,icon);

 if(pace==-1) *string=0;
 else
 sprintf(string,"%d",pace);
}



/*****************************************************************************/

#ifdef NEVER


int asciichar(int * menu)    /* return either code or -1 */
{
 return(codechar(menuaddr(menu,0)));
}


static void asciigetchar(int * val,int * menu)
{
 int c;
 c=asciichar(menu);
 *val=c;
}



void asciiwrchar(int * menu,int byte)
{
 char * string;

 string=menuaddr(menu,0);

 if(byte==-1) *string=0;
 else         uncode(string,byte);
}


static int asciipace(int * menu)  /* return either pace or -1 */
{
 int    i;
 char * string;

 string=menuaddr(menu,0);

 sscanf(string,"%d",&i);
 return(i-(i==0));
}


void asciigetpace(int * menu,int * val)
{
 int c;
 c=asciipace(menu);
 if(c!=-1) *val=c;
}


void asciigetpace10(int * menu,int * val)
{
 int c;
 c=asciipace(menu);
 if(c!=-1) *val=c*10;
}



void asciiwrpace(int * menu,int pace)
{
 char * string;
 string=menuaddr(menu,0);

 if(pace==-1) *string=0;
 else
 sprintf(string,"%d",pace);
}


#endif


/*****************************************************************************/



int asciioutbyte(int byte)
{
 if(txtrans) byte=txtable[byte];
 return(outbyte(byte));
}



int asciiserialgetbyte(void)
{
 int byte=getbyte();
 if(byte!=-1 && rxtrans) byte=rxtable[byte];
 return(byte);
}




/* ascii send byte to serial port */

void asciiout(int byte,int time)
{
 asciioutbyte(byte);
 if(asctxe) tty(byte);

 if(time!=-1)
 {
  time+=clock();
  while(clock()<time)
  {
   pollzt();
   if(!ftp_ok) break;
  }
 }
}


/*****************************************************************************/

static int    bsize;
static int    bpoint;
static int    asciioneshot;
static int    asciionefile;


void asciisetone(int filen)
{
 asciioneshot=1;
 asciionefile=filen;
}




FILE * asciireadfile(void)
{
 int bn;

 if(asciioneshot)
 {
  bn=asciionefile;
  asciioneshot=0;
 }
 else
 {
  bn=txbatchnext();
  if(bn==-1) return(NULL);
 }

 bsize=0;
 bpoint=0;

 return(ftpopenread(bn,0));
}



int asciigetbytesub(FILE * fp,char * buffer)
{
 if((bsize-bpoint)==0)
 {
  bsize=ftpread(buffer,1,512,fp);
  bpoint=0;
 }

 if(bsize==bpoint) return(ASCIIEOF);

 return(buffer[bpoint++]);
}



static int agetbyte;
static int agetbyte2;



int asciigetbyte(FILE * fp,char * buffer)
{
 agetbyte=asciigetbytesub(fp,buffer);
 agetbyte2=-1;

 if(agetbyte==LF || agetbyte==CR)
 {
  agetbyte2=asciigetbytesub(fp,buffer);

  if(agetbyte2!=ASCIIEOF)
  {
   if(agetbyte==LF && agetbyte2==CR) return(ASCIIEOL);
   else
   if(agetbyte==CR && agetbyte2==LF) return(ASCIIEOL);
   bpoint--;
   agetbyte2=-1;
  }
  else agetbyte2=-1;


  return(ASCIIEOL);
 }

 return(agetbyte);
}


void asciiclosereadfile(FILE * fp,char * message,int error)
{
 ftpcloseread(fp,message,error?FTPCLOSEERROR:0);
}


/*****************************************************************************/


FILE * asciiwritefile(void)
{
 FILE * fp;

 bsize=512;
 bpoint=0;

 fp=ftpopenwrite("ASCII",NULL,0,0,NULL,NULL);
 return(fp);
}


int asciiputbyte(int byte,FILE * fp,char * buffer)
{
 buffer[bpoint++]=byte;
 if(bpoint==bsize)
 {
  ftpwrite(buffer,1,bsize,fp);
  bpoint=0;
 }
 return(byte);
}


void asciiclosewritefile(FILE * fp,char * message,int error,char * buffer)
{
 ftpwrite(buffer,1,bpoint,fp);
 ftpclosewrite(fp,message,error?FTPCLOSEERROR:0);
}



/*****************************************************************************/



/* ascii send file */

int asciitx(void)
{
 int     byte;
 int     lastbyte;
 int     otxonf;
 int     txonf;
 FILE *  fp;
 char *  message=NULL;
 char    buff[512];
 int     error=0;
 int     pcount=0;

 if((fp=asciireadfile())==NULL) return(1);

 otxonf=ftpflow();
 byte=lastbyte=!ASCIIEOL;

 if(txbegin!=-1) asciioutbyte(txbegin);

 while(1)
 {
  if(pcount>(txbyterate/2))
  {
   pcount=ftpoutputchars();
   while(pcount>(txbyterate/4))
   {
    if(otxonf!=(txonf=ftpflow()) && flow==2)
    {
     otxonf=txonf;
     if(txonf) ftpinfo("{ASC00}");
     else      ftpinfo("{ASC01}");
    } 

    pollzt();
    if(!ftp_ok) break;
    pcount=ftpoutputchars();
   } 
   pcount=0;
  }
  else
  { 
   pcount++;

   byte=asciigetbyte(fp,buff);

   if(byte==ASCIIEOL)
   {
    if(lastbyte==ASCIIEOL && txexpand) asciiout(SPC,txcharpace);

    switch(txeol)
    {
       case ASCIILF:
                    asciiout(LF,txlinepace);
                    break;

       case ASCIICR:
                    asciiout(CR,txlinepace);
                    break;

     case ASCIILFCR:  
                    asciiout(LF,txcharpace);
                    asciiout(CR,txlinepace);
                    break;

     case ASCIICRLF:
                    asciiout(CR,txcharpace);
                    asciiout(LF,txlinepace);
                    break;

      case ASCIIRAW:
                    if(agetbyte2!=-1)
                    {
                     asciiout(agetbyte,txcharpace);
                     asciiout(agetbyte2,txlinepace);
                    }
                    else
                     asciiout(agetbyte,txlinepace);
                    break;
    }

    if(txprompt!=-1) 
    {
     ftpinfo("{ASC02}");
     ftp_cont=1;
     while(tty(asciiserialgetbyte())!=txprompt && ftp_cont)
     {
      pollzt();
      if(!ftp_ok) break;
     }
     ftpinfo("");
    }
   }
   else
   if(byte==ASCIIEOF) break;
   else               asciiout(byte,txcharpace);
  }
  lastbyte=byte;


  byte=tty(asciiserialgetbyte());
  if(byte!=-1 && byte==txstop && ftp_ok)
  {
   ftpinfo("{ASC03}");
   ftp_cont=1;
   while(tty(asciiserialgetbyte())!=txstart && ftp_cont)
   {
    pollzt();
    if(!ftp_ok) break;
   }
   ftpinfo("");
  }


  if(!ftp_ok)
  {
   message="{ASC04}";
   error=1;
   break;
  }

  if(ftpreaderror(fp))
  {
   message="{ASC05}";
   error=1;
   break;
  }
 }

 if(txend!=-1) asciioutbyte(txend);

 if(!message) message="{ASC06}";

 asciiclosereadfile(fp,message,error);

 return(error);
}







/* ascii receive file */

int asciirx(void)
{
 int    byte;
 int    time;
 FILE * fp;
 char * message=NULL;
 int    error=0;
 char   buffer[512];

 if((fp=asciiwritefile())==NULL) return(1);

 if(rxbegin!=-1)
 {
  ftp_cont=1;
  ftpinfo("{ASC07}");
  while(asciiserialgetbyte()!=rxbegin && ftp_cont)
  {
   pollzt();
   if(!ftp_ok) break;
  }
  ftpinfo("");
 }

 time=0;

 while(1)
 {
  byte=asciiserialgetbyte();
  if(byte==-1 && rxtprompt!=-1 && rxpace!=-1 && time>rxpace)
  {
   asciioutbyte(rxtprompt);
   time=0;
   continue;
  }
  else
  if(byte==-1)
  {
   pollzt();
   if(!ftp_ok) 
   {
    message="{ASC04}";
    error=1;
    break;
   }

   if(ftpwriteerror(fp))
   {
    message="{ASC05}";
    error=1;
    break;
   }

   continue;
  }
  else
  if(byte==rxend) break;
  else
  if( rxprompt!=-1 && 
      ((rxeol==ASCIICR && byte==CR) || (rxeol==ASCIILF && byte==LF))
    ) asciioutbyte(rxprompt);

  asciiputbyte(byte,fp,buffer);

  if(ascrxe) tty(byte);
 }

 if(!message) message="{ASC06}";

 asciiclosewritefile(fp,message,error,buffer);

 return(error);
}


/*****************************************************************************/


#ifdef NEVER

void setpopascii(void)
{
 int i;

 for(i=0;i<2;i++) tickst(arxeolchar_menu,i,i==rxeol);
 tickst(arxparams_menu,6,ascrxe); 

 asciiwrpace(arxtime_menu,rxpace/10);

 asciiwrchar(arxprompt_menu,rxprompt);
 asciiwrchar(arxcont_menu,rxtprompt);
 asciiwrchar(arxbeginchar_menu,rxbegin);
 asciiwrchar(arxendchar_menu,rxend);

 for(i=0;i<4;i++) tickst(atxeolchar_menu,i,i==txeol);
 tickst(atxparams_menu,8,txexpand);
 tickst(atxparams_menu,9,asctxe);

 asciiwrpace(atxcharpace_menu,txcharpace);
 asciiwrpace(atxlinepace_menu,txlinepace/10);

 asciiwrchar(atxprompt_menu,txprompt);
 asciiwrchar(atxbeginchar_menu,txbegin);
 asciiwrchar(atxendchar_menu,txend);
 asciiwrchar(atxstartchar_menu,txstart);
 asciiwrchar(atxstopchar_menu,txstop);
}




void decodeascii(int m1,int m2,int m3)
{
 if(m1==1)
  switch(m2)               /* RX */
  {
   case  0:  /* prompt */
           asciigetchar(&rxprompt,arxprompt_menu);
           break;

   case  1:  /* EOL */
           if(m3==0) rxeol=ASCIICR;
           else
           if(m3==1) rxeol=ASCIILF;
           break;

   case  2:  /* Continue */
           asciigetchar(&rxtprompt,arxcont_menu);
           break;

   case  3:  /* Timeout */
           asciigetpace10(arxtime_menu,&rxpace);
           break;

   case  4:  /* begin char */
           asciigetchar(&rxbegin,arxbeginchar_menu);
           break;

   case  5:  /* end char */
           asciigetchar(&rxend,arxendchar_menu);
           break;

   case  6:  /* local echo */
           ascrxe^=1;
           break;
  }
 else
 if(m1==0)                 /* TX */
  switch(m2)
  {
   case  0: /* prompt */
           asciigetchar(&txprompt,atxprompt_menu);
           break;

   case  1: /* EOL */
           if(m3==0) txeol=ASCIICR;
           else
           if(m3==1) txeol=ASCIILF;
           else
           if(m3==2) txeol=ASCIICRLF;
           else
           if(m3==3) txeol=ASCIILFCR;
           break;

   case  2: /* begin */
           asciigetchar(&txbegin,atxbeginchar_menu);
           break;

   case  3: /* end */
           asciigetchar(&txend,atxendchar_menu);
           break;

   case  4: /* start */
           asciigetchar(&txstart,atxstartchar_menu);
           break;

   case  5: /* stop */
           asciigetchar(&txstop,atxstopchar_menu);
           break;

   case  6: /* char pace */
           asciigetpace(atxcharpace_menu,&txcharpace);
           break;

   case  7: /* line pace */
           asciigetpace10(atxlinepace_menu,&txlinepace);
           break;

   case  8: /* expand lines */
           txexpand^=1;
           break;

   case  9: /* local echo */
           asctxe^=1;
           break;
  }
}

#endif


/*****************************************************************************/

int temprxeol;
int temptxeol;
int tempascrxe;
int temptxexpand;
int tempasctxe;


static char * asceolnames[5]={"ASCCR","ASCLF","ASCCRLF","ASCLFCR","ASCRAW"};

static void wrasctxeol(void)
{
 writeicon(whandle[ASCII],13,transtoken(asceolnames[temptxeol]));
}


static void wrascrxeol(void)
{
 writeicon(whandle[ASCII],33,transtoken(asceolnames[temprxeol]));
}



static void asciiok(void)
{
                                        /* RX */
 xasciigetchar(&rxprompt,ewindow,30);   /* prompt */
 xasciigetchar(&rxtprompt,ewindow,34);  /* Continue */
 xasciigetpace10(ewindow,35,&rxpace);   /* Timeout */
 xasciigetchar(&rxbegin,ewindow,36);    /* begin char */
 xasciigetchar(&rxend,ewindow,37);      /* end char */

                                           /* TX */
 xasciigetchar(&txprompt,ewindow,10);      /* prompt */
 xasciigetchar(&txbegin,ewindow,14);       /* begin */
 xasciigetchar(&txend,ewindow,15);         /* end */
 xasciigetchar(&txstart,ewindow,16);       /* start */
 xasciigetchar(&txstop,ewindow,17);        /* stop */
 xasciigetpace(ewindow,18,&txcharpace);    /* char pace */
 xasciigetpace10(ewindow,19,&txlinepace);  /* line pace */

 txeol=temptxeol;
 txexpand=temptxexpand;
 asctxe=tempasctxe;
 rxeol=temprxeol;
 ascrxe=tempascrxe;
}



              /* N L R D U */

static char entryiclst[12][5]=
{
         10,          0,          30,          14,            0,
         14,          0,          34,          15,           10,
         15,          0,          35,          16,           14,
         16,          0,          36,          17,           15,
         17,          0,          37,          18,           16,
         18,          0,           0,          19,           17,
         19,          0,           0,          30,           18,
         30,         10,           0,          34,           19,
         34,         14,           0,          35,           30,
         35,         15,           0,          36,           34,
         36,         16,           0,          37,           35,
         37,         17,           0,           0,           36
};




void asciikey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               zapmenu();
               break;

       case CR:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<12;j++) if(entryiclst[j][0]==icon) break;
               cicon=entryiclst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[ASCII],cicon);
               break;

    default:return;
 }
 *key=-1;
}





void asciiicon(void)
{
 switch(icon)
 {
  case 11:
  case 12:
          if((buttons==0x4 && icon==11) || (buttons==0x1 && icon==12))
          {
           if(temptxeol>ASCIICR)
           {
            temptxeol--;
            wrasctxeol();
           }
          }
          else
          if((buttons==0x1 && icon==11) || (buttons==0x4 && icon==12))
          {
           if(temptxeol<ASCIIRAW)
           {
            temptxeol++;
            wrasctxeol();
           }
          }
          break;


  case 31:
  case 32:
          if((buttons==0x4 && icon==31) || (buttons==0x1 && icon==32))
          {
           if(temprxeol>ASCIICR)
           {
            temprxeol--;
            wrascrxeol();
           }
          }
          else
          if((buttons==0x1 && icon==31) || (buttons==0x4 && icon==32))
          {
           if(temprxeol<ASCIILF)
           {
            temprxeol++;
            wrascrxeol();
           }
          }
          break;


  case 20:  /* TX expand */
          selectst(ewindow,20,temptxexpand^=1);
          break;

  case 21:  /* TX local echo */
          selectst(ewindow,21,tempasctxe^=1);
          break;

  case 38:  /* RX local echo */
          selectst(ewindow,38,tempascrxe^=1);
          break;

  case 39:
          asciiok();
          if(buttons==0x4) zapmenu();
          break;
 }
}



int asciisetup(void)
{
 int handle=createwindow(ASCII);
 
 temprxeol=rxeol;
 tempascrxe=ascrxe;

 selectst(handle,38,ascrxe); 
 wrascrxeol();

 xasciiwrpace(handle,35,rxpace/10);

 xasciiwrchar(handle,30,rxprompt);
 xasciiwrchar(handle,34,rxtprompt);
 xasciiwrchar(handle,36,rxbegin);
 xasciiwrchar(handle,37,rxend);

 temptxeol=txeol;
 temptxexpand=txexpand;
 tempasctxe=asctxe;

 selectst(handle,20,txexpand);
 selectst(handle,21,asctxe);
 wrasctxeol();

 xasciiwrpace(handle,18,txcharpace);
 xasciiwrpace(handle,19,txlinepace/10);

 xasciiwrchar(handle,10,txprompt);
 xasciiwrchar(handle,14,txbegin);
 xasciiwrchar(handle,15,txend);
 xasciiwrchar(handle,16,txstart);
 xasciiwrchar(handle,17,txstop);

 return(handle);
}


